import { createSlice, nanoid, PayloadAction } from '@reduxjs/toolkit'
import { ComponentPropsType } from '../../components/QuestionComponents'
import { getNextSelectedId, insertNewComponent } from './ultils'
import cloneDeep from 'lodash.clonedeep'
import { arrayMove } from '@dnd-kit/sortable'
export type ComponentInfoType = {
  fe_id: string
  type: string
  title: string
  isHidden?: boolean
  isLocked?: boolean
  props: ComponentPropsType
}
export type ComponentStateType = {
  selectedId: string
  componentList: Array<ComponentInfoType>
  copiedComponent: ComponentInfoType | null
}

const INIT_STATE: ComponentStateType = {
  selectedId: '',
  componentList: [],
  copiedComponent: null,
}
export const componentSlice = createSlice({
  name: 'components',
  initialState: INIT_STATE,
  reducers: {
    resetComponents: (state: ComponentStateType, action: PayloadAction<ComponentStateType>) => {
      return action.payload
    },
    changeSelectedId: (state: ComponentStateType, action: PayloadAction<string>) => {
      return { ...state, selectedId: action.payload }
    },
    addComponent: (state: ComponentStateType, action: PayloadAction<ComponentInfoType>) => {
      const newComponent = action.payload
      return insertNewComponent(state, newComponent)
    },
    changeComponentProps(
      state: ComponentStateType,
      action: PayloadAction<{ fe_id: string; newProps: ComponentPropsType }>
    ) {
      const { fe_id, newProps } = action.payload
      const l = state
      const curComp = l.componentList.find(c => c.fe_id === fe_id)
      if (curComp) {
        curComp.props = {
          ...curComp.props,
          ...newProps,
        }
      }
      return l
    },
    removeSelectedComponent(state) {
      const l = state
      const { componentList = [], selectedId: removeId } = l

      const newSelectedId = getNextSelectedId(removeId, componentList)
      l.selectedId = newSelectedId
      const index = componentList.findIndex(c => c.fe_id == removeId)
      componentList.splice(index, 1)
      return l
    },
    changeComponentHidden(
      state: ComponentStateType,
      action: PayloadAction<{ fe_id: string; isHidden: boolean }>
    ) {
      const l = state
      const { componentList = [] } = l
      const { fe_id, isHidden } = action.payload
      let newSelectedId = ''
      if (isHidden) {
        newSelectedId = getNextSelectedId(fe_id, componentList)
      } else {
        newSelectedId = fe_id
      }
      l.selectedId = newSelectedId
      const curComp = componentList.find(c => c.fe_id === fe_id)
      if (curComp) {
        curComp.isHidden = isHidden
      }
      return l
    },
    toggleComponentLocked(state: ComponentStateType, action: PayloadAction<{ fe_id: string }>) {
      const l = state
      const { componentList = [] } = l
      const { fe_id } = action.payload
      const curComp = componentList.find(c => c.fe_id === fe_id)
      if (curComp) {
        curComp.isLocked = !curComp.isLocked
      }
      return l
    },
    copySelectedComponent(state: ComponentStateType) {
      const l = state
      const { componentList = [], selectedId } = l
      const selectedComponent = componentList.find(c => c.fe_id === selectedId)
      if (selectedComponent) {
        l.copiedComponent = cloneDeep(selectedComponent)
      }
      return l
    },
    pasteCopiedComponent(state: ComponentStateType) {
      const { copiedComponent } = state
      if (copiedComponent === null) return
      copiedComponent.fe_id = nanoid()
      return insertNewComponent(state, copiedComponent)
    },
    selectPrevComponent(state: ComponentStateType) {
      const l = state
      const { selectedId, componentList } = state
      const selectedIndex = componentList.findIndex(c => c.fe_id == selectedId)
      if (selectedIndex <= 0) return

      l.selectedId = componentList[selectedIndex - 1].fe_id
      return l
    },
    selectedNextComponent(state: ComponentStateType) {
      const l = state
      const { selectedId, componentList } = state
      const selectedIndex = componentList.findIndex(c => c.fe_id == selectedId)
      if (selectedIndex + 1 === componentList.length) return
      l.selectedId = componentList[selectedIndex + 1].fe_id
      return l
    },
    changeComponentTitle(
      state: ComponentStateType,
      action: PayloadAction<{ fe_id: string; title: string }>
    ) {
      const l = state
      const { title, fe_id } = action.payload
      const curComp = l.componentList.find(c => c.fe_id == fe_id)
      if (curComp) curComp.title = title
      return l
    },
    moveComponent: (
      state: ComponentStateType,
      action: PayloadAction<{ oldIndex: number; newIndex: number }>
    ) => {
      const l = state
      const { componentList: curComponentList } = l
      const { oldIndex, newIndex } = action.payload
      l.componentList = arrayMove(curComponentList, oldIndex, newIndex)
    },
  },
})
export const {
  selectedNextComponent,
  resetComponents,
  selectPrevComponent,
  changeSelectedId,
  removeSelectedComponent,
  addComponent,
  changeComponentProps,
  changeComponentHidden,
  pasteCopiedComponent,
  toggleComponentLocked,
  copySelectedComponent,
  changeComponentTitle,
  moveComponent,
} = componentSlice.actions
export default componentSlice.reducer
